package org.jpropelleralt.collection;

import java.util.Collection;

import org.jpropelleralt.box.Box;
import org.jpropelleralt.change.Change;
import org.jpropelleralt.list.ListBox;
import org.jpropelleralt.list.ListChange;
import org.jpropelleralt.node.Node;
import org.jpropelleralt.reaction.Reaction;

/**
 * A {@link CollectionBox} is a {@link Collection} that also implements
 * {@link Box} to allow tracking of changes to the {@link Collection}
 * and its contents.
 *
 * <p/>
 * When any data reachable from the {@link Collection} changes, a
 * {@link Change} is propagated. This can occur in one of two ways:
 * <p/>
 * When a {@link Collection} method like {@link Collection#clear()} is
 * called, a shallow {@link Change} is propagated, showing that 
 * different instances are now contained in the {@link Collection}.
 * <p/>
 * When contents of the {@link Collection} themselves have a change,
 * for example if the {@link Collection} contains a {@link Node}, and
 * this {@link Node} is changed, a deep {@link Change} is propagated.
 * The {@link Collection} still contains the same instances, but those
 * instances have had {@link Change}s.
 * <p/>
 * Changes produced by {@link CollectionBox} implementations are often 
 * a specific type of {@link Change} giving details of the scope and 
 * type of change that has occurred, in terms of the particular 
 * {@link Collection} interface(s) implemented - see for example {@link ListChange}.
 * <p/>
 * See {@link ListBox}, {@link SetBox}, {@link MapBox}
 * 
 * @param <E>		The type of element in the {@link Collection}
 */
public interface CollectionBox<E> extends Box, Collection<E> {
	
	/**
	 * Clear all {@link Collection} values, then replace them with the new contents,
	 * in the order returned by the iterable. This is done as an "atomic"
	 * change, so only one large change will occur
	 * @param newContents	The new contents
	 */
	public void replace(Iterable<E> newContents);
	
	/**
	 * Replace the contents from a {@link Reaction}
	 * MUST only be used by {@link Reaction}s
	 * @param newContents	The new contents
	 * @param propagate		True to propagate the change,
	 * 						false to just make the alteration.
	 */
	public void reactionReplace(Iterable<E> newContents, boolean propagate);
}
